package org.mte.sakn.log;

import java.io.File;
import java.io.IOException;

import org.apache.log4j.RollingFileAppender;
import org.apache.log4j.helpers.CountingQuietWriter;
import org.apache.log4j.helpers.LogLog;

/**
 * MTERollingFileAppender from org.apache.log4j.RollingFileAppender
 *
 * @author Marco Traversari
 * @version $Revision: 1.1 $ $Date: 2011-04-18 08:38:11 $
 */
public class MTERollingFileAppender extends RollingFileAppender {

    /**
     * Implements the usual roll over behaviour.
     *
     * <p>
     * If <code>MaxBackupIndex</code> is positive, then files {<code>File.1</code>,
     * ..., <code>File.MaxBackupIndex -1</code>} are renamed to {<code>File.2</code>,
     * ..., <code>File.MaxBackupIndex</code>}. Moreover, <code>File</code>
     * is renamed <code>File.1</code> and closed. A new <code>File</code> is
     * created to receive further log output.
     *
     * <p>
     * If <code>MaxBackupIndex</code> is equal to zero, then the
     * <code>File</code> is truncated with no backup files created.
     *
     */
    public// synchronization not necessary since doAppend is alreasy synched
    void rollOver() {
        File target;
        File file;
        if (qw != null) {
            LogLog.debug("rolling over count="
                    + ((CountingQuietWriter) qw).getCount());
        }
        LogLog.debug("maxBackupIndex=" + maxBackupIndex);

        // If maxBackups <= 0, then there is no file renaming to be done.
        if (maxBackupIndex > 0) {
            // Delete the oldest file, to keep Windows happy.
//            file = new File(fileName + '.' + maxBackupIndex);
            file = new File(buildBackupFileName(fileName, maxBackupIndex));
            if (file.exists())
                file.delete();

            // Map {(maxBackupIndex - 1), ..., 2, 1} to {maxBackupIndex, ..., 3,
            // 2}
            for (int i = maxBackupIndex - 1; i >= 1; i--) {
//                file = new File(fileName + "." + i);
                file = new File(buildBackupFileName(fileName, i));
                if (file.exists()) {
//                    target = new File(fileName + '.' + (i + 1));
                    target = new File(buildBackupFileName(fileName, i + 1));
                    LogLog.debug("Renaming file " + file + " to " + target);
                    file.renameTo(target);
                }
            }

            // Rename fileName to fileName.1
//            target = new File(fileName + "." + 1);
            target = new File(buildBackupFileName(fileName, 1));

            this.closeFile(); // keep windows happy.

            file = new File(fileName);
            LogLog.debug("Renaming file " + file + " to " + target);
            file.renameTo(target);
        }

        try {
            // This will also close the file. This is OK since multiple
            // close operations are safe.
            this.setFile(fileName, false, bufferedIO, bufferSize);
        } catch (IOException e) {
            LogLog.error("setFile(" + fileName + ", false) call failed.", e);
        }
    }

    /**
     * buildBackupFileName
     * @param fileName
     * @param index
     * @return backupFileName
     */
    private String buildBackupFileName(String fileName, int index) {
        int pos = fileName.lastIndexOf(".");
        String backupFileName = fileName.substring(0, pos)
            + "." + index
            + "." + fileName.substring(pos + 1);
        return backupFileName;
    }
}
